package org.xsm.pinyougou.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.xsm.pinyougou.entity.TbSeckillGoods;

import org.xsm.pinyougou.mapper.TbSeckillGoodsMapper;
import org.xsm.pinyougou.service.SeckillService;
import org.xsm.pinyougou.thread.Xc;
import org.xsm.pinyougou.utils.IdWorker;
import org.xsm.pinyougou.utils.OrderRecord;
import org.xsm.pinyougou.utils.Result;
import org.xsm.pinyougou.utils.SystemConst;


import java.util.Date;
import java.util.List;
import java.util.concurrent.Executor;


@Service
@Transactional
@Component      // 定时任务
public class SeckillServiceImpl implements SeckillService {


    @Autowired
    TbSeckillGoodsMapper tbSeckillGoodsMapper;

    /**
     * 获取商品信息
     */
    @Override
    public List<TbSeckillGoods> findAll() {

        // 先从redis里查数据
        List<TbSeckillGoods> values = redisTemplate.boundHashOps(TbSeckillGoods.class.getSimpleName()).values();

        if(values.size() > 0){

            return values;

        }else {
            // 如果没有则从数据库里查，并把查到的数据放到redis
            List<TbSeckillGoods> byTj = tbSeckillGoodsMapper.findByTj();
            for (TbSeckillGoods t: byTj){

                redisTemplate.boundHashOps(TbSeckillGoods.class.getSimpleName()).put(t.getId(), t);

                // 为了解决超卖问题：
                // 创建1个集合，这个集合的名字是id，里面存的都是id,数量和商品的剩余数量一样
                // 卖出去一个，就减去一个，这样就不会超卖了
                saveList(t.getId(), t.getStockCount());

            }


            return byTj;

        }



    }

    @Autowired
    RedisTemplate redisTemplate;


    @Override
    public TbSeckillGoods findOne(Long id) {
        return (TbSeckillGoods) redisTemplate.boundHashOps(TbSeckillGoods.class.getSimpleName()).get(id);
    }

    @Autowired
    IdWorker idWorker;

    @Autowired
    Xc xc;


    @Autowired
    Executor executor;  // 线程

    /**
     *
     * 1、记录这个用户，已下单，未支付. 用于防止重新下单
     * 2、记录这个用户和其下单商品为list集合，key为 OrderRecord，这些订单会保存到数据库，为提高反应速度，先返回下单成功，添加数据库的工作
     * 由另一个线程执行
     * 3、返回下单成功
     */
    @Override
    public Result saveOrder(Long id, String userId) {


        // 判断用户是否已下单
        Boolean member = redisTemplate.boundSetOps(SystemConst.CONST_USER_ID_PREFIX + id).isMember(userId);
        if (member){
            return new Result(false, "有订单未支付");
        }

        id = (Long) redisTemplate.boundListOps(SystemConst.CONST_SECKILLGOODS_ID_PREFIX + id).rightPop();

        // 查看是否还有库存
        if(null == id){
            return new Result(false, "已销售完");
        }

        // 记录已下单，但未支付的用户
        redisTemplate.boundSetOps(SystemConst.CONST_USER_ID_PREFIX + id).add(userId);


        OrderRecord orderRecord = new OrderRecord(id, userId);

        // 记录用户下单信息，商品id和用户userId
        redisTemplate.boundListOps(OrderRecord.class.getSimpleName()).leftPush(orderRecord);

        // 启动线程，把商品下单信息记录到redis
        executor.execute(xc);


        return new Result(true, "下单成功");
    }





    public  void saveList(Long id, Integer stockCount){

        for (int i = 0; i<stockCount; i++){
            redisTemplate.boundListOps(SystemConst.CONST_SECKILLGOODS_ID_PREFIX+id).leftPush(id);
        }
    }
}
